﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Xml;

namespace D.Wx
{
    [Serializable]
    /// <summary>
    /// 微信推送消息的公共参数类，微信公众号推送消息事件-接收普通消息
    /// 当普通微信用户向公众账号发消息时，微信服务器将POST消息的XML数据包到开发者填写的URL上。需要开发者服务器对xml数据包进行解析然后回复微信客户端应答操作的指令。
    /// 官网地址：https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html#
    /// </summary>
    public class WeiXinXmlMessage
    {

        [JsonProperty(Order = -100)]
        /// <summary>
        /// 开发者 微信号
        /// </summary>
        public string ToUserName { get; set; }
        [JsonProperty(Order = -99)]
        /// <summary>
        /// 发送方帐号（一个OpenID）
        /// </summary>
        public string FromUserName { get; set; }
        [JsonProperty(Order = -98)]
        /// <summary>
        /// 消息创建时间 （整型）
        /// </summary>
        public string CreateTime { get; set; }
        [JsonProperty(Order = -98)]
        [JsonConverter(typeof(StringEnumConverter))]
        /// <summary>
        /// 消息类型，event
        /// </summary>
        public MessageType MsgType { get; set; }
        /// <summary>
        /// 解析微信消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public static T Load<T>(string xmlString) where T : WeiXinXmlMessage
        {
            ///正则表达式 去除xml中 CDATA属性标签
            xmlString = xmlString.Replace("<![CDATA[", "").Replace("]]>", "");
            ///加载xml
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlString);
            ///xml转换成json
            string jsonString = JsonConvert.SerializeXmlNode(doc);
            ///反序列化json
            XmlRoot<T> xmlroot = JsonConvert.DeserializeObject<XmlRoot<T>>(jsonString);
            ///返回根节点信息
            return xmlroot.xml;
        }
        /// <summary>
        /// 序列化为xml字符串
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static string SerializeXml(object model)
        {
            ///按照接口文档字段进行格式封装
            object xmlModel = new { xml = model };
            string jsonString = JsonConvert.SerializeObject(xmlModel);
            XmlDocument xml = JsonConvert.DeserializeXmlNode(jsonString);
            return xml.InnerXml;
        }
        /// <summary>
        /// 根节点信息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        class XmlRoot<T> where T : WeiXinXmlMessage
        {
            /// <summary>
            /// 根节点
            /// </summary>
            public T xml { get; set; }
        }
    }


    /// <summary>
    /// 文本消息
    /// 实例：
    /// string xml = @"<xml><ToUserName><![CDATA[gh_e136c6e50636]]></ToUserName>
    /// <FromUserName><![CDATA[oMgHVjngRipVsoxg6TuX3vz6glDg]]></FromUserName>
    /// <CreateTime>1408090502</CreateTime>
    /// <MsgType><![CDATA[event]]></MsgType>
    /// <Event><![CDATA[scancode_push]]></Event>
    /// <EventKey><![CDATA[6]]></EventKey>
    /// </xml>";
    /// 调用：TextMessageResponse response = WeiXinXmlMessage.Load<TextMessageResponse>(xml);
    /// </summary>
    public class TextMessageResponse : WeiXinXmlMessage
    {
        /// <summary>
        /// 文本消息内容
        /// </summary>
        public string Content { get; set; }
        /// <summary>
        /// 消息id，64位整型
        /// </summary>
        public string MsgId { get; set; }
    }


    /// <summary>
    /// 图片消息
    /// 实例，参考文本消息
    /// 调用：ImageMessageResponse response = WeiXinXmlMessage.Load<ImageMessageResponse>(xml);
    /// </summary>
    public class ImageMessageResponse : WeiXinXmlMessage
    {
        /// <summary>
        /// 图片链接（由系统生成）
        /// </summary>
        public string PicUrl { get; set; }
        /// <summary>
        ///  图片消息媒体id，可以调用获取临时素材接口拉取数据。
        /// </summary>
        public string MediaId { get; set; }
        /// <summary>
        /// 消息id，64位整型
        /// </summary>
        public string MsgId { get; set; }
    }

    /// <summary>
    /// 语音消息
    /// 调用：ImageMessageResponse response = WeiXinXmlMessage.Load<ImageMessageResponse>(xml);
    /// </summary>
    public class VoiceMessageResponse : WeiXinXmlMessage
    {
        /// <summary>
        /// 语音格式，如amr，speex等
        /// </summary>
        public string Format { get; set; }
        /// <summary>
        ///  图片消息媒体id，可以调用获取临时素材接口拉取数据。
        /// </summary>
        public string MediaId { get; set; }
        /// <summary>
        /// 消息id，64位整型
        /// </summary>
        public string MsgId { get; set; }
    }

    /// <summary>
    /// 视频消息
    /// 调用： VideoMessageResponse response = WeiXinXmlMessage.Load<VideoMessageResponse>(xml);
    /// </summary>
    public class VideoMessageResponse : WeiXinXmlMessage
    {
        /// <summary>
        /// 视频消息缩略图的媒体id，可以调用多媒体文件下载接口拉取数据。
        /// </summary>
        public string ThumbMediaId { get; set; }
        /// <summary>
        ///  视频消息媒体id，可以调用获取临时素材接口拉取数据。
        /// </summary>
        public string MediaId { get; set; }
        /// <summary>
        /// 消息id，64位整型
        /// </summary>
        public string MsgId { get; set; }
    }

    /// <summary>
    /// 地理位置消息
    /// 调用：VideoMessageResponse response = WeiXinXmlMessage.Load<VideoMessageResponse>(xml);
    /// </summary>
    public class LocationMessageResponse : WeiXinXmlMessage
    {
        /// <summary>
        /// 地理位置纬度
        /// </summary>
        public string Location_X { get; set; }
        /// <summary>
        /// 地理位置经度
        /// </summary>
        public string Location_Y { get; set; }
        /// <summary>
        /// 地图缩放大小
        /// </summary>
        public string Scale { get; set; }
        /// <summary>
        /// 地理位置信息
        /// </summary>
        public string Label { get; set; }
        /// <summary>
        /// 消息id，64位整型
        /// </summary>
        public string MsgId { get; set; }
    }

    /// <summary>
    /// 链接消息
    /// 调用：LinkMessageResponse response = WeiXinXmlMessage.Load<LinkMessageResponse>(xml);
    /// </summary>
    public class LinkMessageResponse : WeiXinXmlMessage
    {
        /// <summary>
        /// 消息标题
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// 消息描述
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        /// 消息链接
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        /// 消息id，64位整型
        /// </summary>
        public string MsgId { get; set; }
    }

    /// <summary>
    /// 消息类型
    /// </summary>
    public enum MessageType
    {
        /// <summary>
        /// 文本消息
        /// </summary>
        text,
        /// <summary>
        /// 图片
        /// </summary>
        image,
        /// <summary>
        /// 语音消息
        /// </summary>
        voice,
        /// <summary>
        /// 视频消息
        /// </summary>
        video,
        /// <summary>
        /// 短视频消息
        /// </summary>
        shortvideo,
        /// <summary>
        /// 定位消息
        /// </summary>
        location,
        /// <summary>
        /// 超链接跳转事件
        /// </summary>
        @link,
        /// <summary>
        /// 菜单点击事件
        /// </summary>
        @event
    }
}
